package com.kitty.game.enter;

import com.kitty.common.utils.SpringUtils;
import com.kitty.game.ServerService;
import com.kitty.game.config.GameMap;
import com.kitty.game.config.Transfer;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.map.service.MapService;
import com.kitty.game.player.PlayerService;
import com.kitty.game.role.model.Account;
import com.kitty.game.role.model.Role;
import com.kitty.game.role.service.RoleService;
import com.kitty.game.utils.*;
import com.kitty.listener.EventDispatcher;
import com.kitty.listener.EventType;
import com.kitty.listener.event.EnterMapEvent;
import com.kitty.listener.event.LeaveMapEvent;
import com.kitty.listener.event.RoleExpireEvent;

import com.kitty.mina.annotation.RequestMapping;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.cache.SessionUtils;
import com.kitty.mina.message.MessagePusher;
import com.kitty.mina.session.SessionManager;
import com.kitty.mina.session.SessionProperties;

import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.session.IoSession;
import org.nutz.lang.Lang;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;

//后加
import com.kitty.game.server.message.ReqAskServerTime;
import com.kitty.game.server.message.ReqRequestServerStatus;
import com.kitty.game.server.message.ReqSwitchLine;
import com.kitty.game.server.message.RespOtherLogin;
import com.kitty.game.server.message.RespReplyServerTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Controller
@Slf4j
public class EnterGameController {
    @Autowired
    private PlayerService playerService;

    /**
     * 后台切回来的时候请求的包
     */
    @RequestMapping
    public void refreshUserData(IoSession session, ReqRefreshUserData refreshUserData) {
        Role role = SessionUtils.getRoleBySession(session);
        SpringUtils.getNpcService().closeDlg(role, "WaitDlg");
        RoleService roleService = SpringUtils.getRoleService();
        try {
            /**后台切回游戏时 客户端好像清除了某些角色数据 这里直接走一遍登录流程算了*/
            Account account = SpringUtils.getAccountService().getAccount(role.getSid());
            synchronized (account) {
                roleService.enterMap(session, role);
            }
        } catch (Exception e) {
            log.error("后台切回报错=={}", role.getName());
        }
    }

    /**
     * 记录客户端错误
     */
    @RequestMapping
    public void clientError(IoSession session, ReqClientErrOccur reqClientErrOccur) {

    }

    /**
     * 加载已存在角色
     *
     * @param session
     */
    @RequestMapping
    public void loadExistedRole(IoSession session, ReqLoadExistedChar req) {
        Role temp = SessionUtils.getRoleBySession(session);
        if (temp != null) {
            if (!temp.getName().equals(req.getChar_name())) {
                log.info("登录出错。关闭连接:"+temp.getName()+"   "+req.getChar_name());
                session.closeNow();
                return;
            }
        }

        long uid = SpringUtils.getPlayerService().getUidBy(req.getChar_name());
        Role role = playerService.getPlayerBy(uid);
        if (role == null){
            log.info("role==null:");
            return;
        }
//        Role role = SpringUtils.getBean(Dao.class).fetch(Role.class, Cnd.where("uid","=",uid));
//        if (role !=null){
//            role.doAfterInit();
//        }
        String sid = SessionManager.INSTANCE.getSessionAttr(session, SessionProperties.ACCOUNT_SID, String.class);
        if (sid == null || !sid.equals(role.getSid())) {
            /**如果Session绑定的sid跟角色sid不一致,应该就是非法登录别人的角色 直接返回 什么也不做*/
            RespOtherLogin respOtherLogin = new RespOtherLogin();
            respOtherLogin.setContent("角色登录失败。#r（原因：9025）");
            respOtherLogin.setResult((short) 0);
            MessagePusher.pushMessage(session, respOtherLogin);
            if (role.getSid() != null) {
               // LoggerFunction.MONOIOR.getLogger().warn("角色登录失败。#r（原因：9025）,sessionSid:{},roleSid:{},roleUid:{},roleName:{}", sid, role.getSid(), role.getUid(), role.getName());
            } else {
               // LoggerFunction.MONOIOR.getLogger().warn("角色登录失败。#r（原因：9025）,sessionSid:{},roleSid:{}");
            }
            log.info("角色登录失败。#r（原因：9025）");
            return;
        }
        Long attr = SessionManager.INSTANCE.getSessionAttr(session, SessionProperties.PLAYER_UID, Long.class);
        if (attr !=null && attr > 0) {
            log.error("角色已登录=UID:{},角色名:{}",attr,SessionManager.INSTANCE.getSessionAttr(session, SessionProperties.PLAYER_NAME, String.class));
            return;
        }
        try {
            if (!SpringUtils.getRoleService().canLogin(role.getSid(),session)){
                log.info("不能登录");
                return;
            }
            Account account = SpringUtils.getAccountService().getAccountNoCache(role.getSid());
            if (account.getIsStop() ==1) {
                RespOtherLogin respOtherLogin = new RespOtherLogin();
                respOtherLogin.setContent("运营中被封闭的帐号，请联系管理员。#r（原因：1033）");
                respOtherLogin.setResult((short) 2);
                MessagePusher.pushMessage(session, respOtherLogin);
                return;
            }
//            if (SpringUtils.getBean(ServerService.class).getCeshi() == 1 && account.getPrivilege() <200){
//                MessagePusher.pushMessage(session,new RespNotifyMiscEx("没有权限"));
//                session.closeNow();
//                return;
//            }
            RoleService roleService = SpringUtils.getRoleService();
            Lock lock = DataCache.UID_LOCK_MAP.getOrDefault(role.getUid(), new ReentrantLock());
            if (lock.tryLock()) {
                try {
                    /**把GM添加到在线GM列表*/
                    if(account.getPrivilege()>= PrivilegeConst.GM){
                        DataCache.ONLINE_GMS_ID.add(role.getUid());
                    }
                    roleService.enterMap(session, role);
                } finally {
                    lock.unlock();
                }
            } else {
                log.error("获取不到锁, 登录=UID:{}", role.getUid());
            }

        } catch (Exception e) {
            log.error(Lang.getStackTrace(e));
        }
    }




    /**
     * 换地图
     *
     * @param session
     * @param reqTelePort
     */

    @RequestMapping
    public void changeMap(IoSession session, ReqTelePort reqTelePort) {
        Role role = SessionUtils.getRoleBySession(session);
        SpringUtils.getBean(MapService.class).changeMap(role, reqTelePort);
    }


    /**
     * 传送阵过图
     *
     * @param session
     * @param reqEnterRoom
     */
    @RequestMapping
    public void enterRoom(IoSession session, ReqEnterRoom reqEnterRoom) {
        Role role = SessionUtils.getRoleBySession(session);
        if (role == null) {
            return;
        }

        Transfer transfer = SpringUtils.getBean(MapService.class).getTrasfer(reqEnterRoom.getMapName(), role.getPos().getMapId());
        if (transfer == null) {
            return;
        }

        MapService mapService = SpringUtils.getBean(MapService.class);
        GameMap gameMap = mapService.getMap(transfer.getToMapId());
        if (gameMap == null) {
            return;
        }
        /**产生一个离开地图事件*/
        int oldMapId = role.getPos().getMapId();
        EventDispatcher.getInstance().fireEvent(new LeaveMapEvent(EventType.LEAVE_MAP, role, oldMapId));


        role.setPos(transfer.getToX(), transfer.getToY(), transfer.getToFangxiang(), transfer.getToMapId());
        role.save();

        /**产生一个进入地图事件*/
        EventDispatcher.getInstance().fireEvent(new EnterMapEvent(EventType.ENTER_MAP, role,oldMapId));

    }


    /**
     * 退出角色
     *
     * @param session
     * @param reqLogout
     */
    @RequestMapping
    public void quiltRole(IoSession session, ReqLogout reqLogout) {
        /**可能需要根据退出原因来不同处理*/
        log.error("退出角色原因==={}", reqLogout.getReason());
        Role role = SessionUtils.getRoleBySession(session);
        /* 在线状态*/
        role.setOn_line(0);
        role.save();
        if(role.getExtendBox().getTuoguanstate()!=1){
            EventDispatcher.getInstance().fireEvent(new RoleExpireEvent(EventType.ROLE_EXPIRE, role));
            SpringUtils.getTeamService().handleRoleExpire(role);
            SpringUtils.getRoleService().removeOffline(role);
        }
//        /**产生一个登出事件*/
//        ThreadLocalUtil.addLocalTask(session, () -> {
//            EventDispatcher.getInstance().fireEvent(new LogoutEvent(EventType.LOGOUT, role));
//        });
    }

    /**
     * 加密验证?
     *
     * @param session
     * @param reqAskServerTime
     */
    @RequestMapping
    public void askServerTime(IoSession session, ReqAskServerTime reqAskServerTime) {

        RespReplyServerTime respReplyServerTime = new RespReplyServerTime();
        respReplyServerTime.setServer_time(new Long(new Date().getTime() / 1000).intValue());
        String ipAddr = session.getRemoteAddress().toString().split(":")[0].replace("/", "");
        respReplyServerTime.setIp(ipAddr);
        MessagePusher.pushMessage(session, respReplyServerTime);
    }

    /**
     * 返回历史角色名
     *
     * @param session
     * @param reqHistoryName
     */
    @RequestMapping
    public void historName(IoSession session, ReqHistoryName reqHistoryName) {
        Role role = SessionUtils.getRoleBySession(session);
        RespFormerName respFormerName = new RespFormerName();
        respFormerName.setNameList(role.getExtendBox().getNameList());
        MessagePusher.pushMessage(session, respFormerName);
    }

    /**
     * 实名认证
     */
    @RequestMapping
    public void realNameAuth(IoSession session, ReqRealNameAuth reqRealNameAuth) {
        RespRealNameAuth respRealNameAuth = new RespRealNameAuth();
        respRealNameAuth.setNameAuth(true);
        respRealNameAuth.setPhoneAuth(true);
        respRealNameAuth.setName("****");
        respRealNameAuth.setPhone("***********");
        respRealNameAuth.setIdCard("******************");
        MessagePusher.pushMessage(session, respRealNameAuth);
    }


    /**
     * 请求线路列表
     */

    @RequestMapping
    public void lineList(IoSession session, ReqRequestServerStatus reqRequestServerStatus) {
        sendLineInfo(session);
    }

    /**
     * 发送线路信息
     *
     * @param session
     */
    private void sendLineInfo(IoSession session) {
        RespChangeLineList respChangeLineList = new RespChangeLineList();
        List<LineInfo> list = new ArrayList<>();
        ServerService serverService = SpringUtils.getBean(ServerService.class);
        DataCache.ID_SERVER.forEach((id, server) -> {
            if (server.getIp().equals(serverService.getServer().getIp()) && server.getPort() == serverService.getServer().getPort()) {
                LineInfo lineInfo = new LineInfo();
                lineInfo.setLineIp(server.getSonIp());
                lineInfo.setLineName(server.getSonName());
                lineInfo.setId((short) server.getId());
                int count = DataCache.ONLINE_ROLES.size();
                if (count >= server.getFull()) {
                    lineInfo.setStatus((short) 5);
                } else if (count >= server.getRed() && count < server.getFull()) {
                    lineInfo.setStatus((short) 4);
                } else if (count >= server.getOrange() && count < server.getRed()) {
                    lineInfo.setStatus((short) 3);
                } else {
                    lineInfo.setStatus((short) 2);
                }
                list.add(lineInfo);
            }
        });
        respChangeLineList.setLinelist(list);
        MessagePusher.pushMessage(session, respChangeLineList);
    }

    /**
     * 换线
     *
     * @param session
     * @param reqSwitchLine
     */
    @RequestMapping
    public void changeLine(IoSession session, ReqSwitchLine reqSwitchLine) {
        RoleService roleService = SpringUtils.getBean(RoleService.class);
        /**产生一个换线事件*///Todo 换线目前没有写 如果有的话是不是应该有一个换线事件?
        roleService.changeLine(session, reqSwitchLine);
    }
}
